﻿using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IO;
using System.Reflection;
using System.Text;
using Urs.Core.Infrastructure;
using Plugin.Api.SwaggerGen;
using Urs.Framework.Infrastructure;

namespace Plugin.Api
{
    public class OpenApiStartup : IUrsStartup
    {
        /// <summary>
        /// Add and configure any of the middleware
        /// </summary>
        /// <param name="services">Collection of service descriptors</param>
        /// <param name="configuration">Configuration of the application</param>
        public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
        {
            services.AddApiVersioning(option =>
            {
                option.ReportApiVersions = true;
                option.AssumeDefaultVersionWhenUnspecified = true;
                option.DefaultApiVersion = new ApiVersion(1, 0);
            });

            //var openApiSettings = EngineContext.Current.Resolve<OpenApiSettings>();
            var openApiSettings =new OpenApiSettings();
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(o =>
            {
                o.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidIssuer = openApiSettings.Issuer,
                    ValidAudience = openApiSettings.Audience,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(openApiSettings.JwtSecurityKey)),
                    ValidateIssuerSigningKey = true,
                    ////是否验证Token有效期，使用当前时间与Token的Claims中的NotBefore和Expires对比
                    ValidateLifetime = true,
                    ////允许的服务器时间偏移量
                    ClockSkew = TimeSpan.Zero
                };
            });

            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
                {
                    Version = "v1",
                    Title = "V1 API文档",
                    Description = "UrShop Api文档"
                });
                //swagger中控制请求的时候发是否需要在url中增加Authorization
                options.OperationFilter<AddAuthTokenHeaderParameter>();
                options.IncludeXmlComments(Path.Combine(Directory.GetCurrentDirectory(), @"Plugins\Plugin.API\Plugin.API.xml"));
                //添加对控制器的标签(描述)
                options.DocumentFilter<SwaggerDocTag>();
                options.CustomSchemaIds(x => x.FullName);
            });

            services.AddMvcCore().AddApiExplorer();
        }

        public class LowercaseContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
        {
            protected override string ResolvePropertyName(string propertyName)
            {
                return propertyName.ToLower();
            }
        }
        /// <summary>
        /// Configure the using of added middleware
        /// </summary>
        /// <param name="application">Builder for configuring an application's request pipeline</param>
        public void Configure(IApplicationBuilder application)
        {
            application.UseSwagger();
            //application.UseSwaggerUI();
            application.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "V1 Docs");
                c.IndexStream = () => Assembly.GetExecutingAssembly()
                    .GetManifestResourceStream("UShopUN.wwwroot.swagger.ui.index.html");
                c.DocExpansion(DocExpansion.None);
            });
            application.Use(async (context, next) =>
            {
                context.Request.EnableBuffering();
                await next();
            });
        }

        public int Order => 1;
    }
}
